use crate::middleware::jwt::admin::Claims;
use crate::service;
use crate::{bootstrap::AppState, router::resp::RespVO};
use axum::body::Body;
use axum::extract::{Path, Query};
use axum::http::Response;
use axum::response::IntoResponse;
use axum::{extract::State, Json};
use serde_json::json;
use sky_pojo::dto::category::{self, CategoryDTO, CategoryPageQueryDTO};
use sky_pojo::dto::enable_disable;
use sky_pojo::entities::category::Model;
use sky_pojo::vo::PageResult;

pub async fn create_category(
    claim: Claims,
    State(state): State<AppState>,
    Json(category_dto): Json<CategoryDTO>,
) -> Response<Body> {
    let result = service::category::insert(state.db_pool, category_dto, claim.id).await;

    match result {
        Ok(model) => {
            tracing::info!("new category {:?}", model);
            return RespVO::<Model>::success("success".to_owned(), Some(model)).into_response();
        }
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn modify_by_id(
    claims: Claims,
    State(state): State<AppState>,
    Json(category_dto): Json<CategoryDTO>,
) -> Response<Body> {
    let result = service::category::modify_by_id(state.db_pool, category_dto, claims.id).await;

    match result {
        Ok(model) => RespVO::<Model>::success("success".to_owned(), Some(model)).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn enable_disable(
    claim: Claims,
    State(state): State<AppState>,
    Path(status): Path<i32>,
    Query(query): Query<enable_disable::EDQuery>,
) -> Response<Body> {
    let dto = CategoryDTO {
        id: Some(query.id),
        r#type: None,
        name: None,
        sort: None,
        status: Some(status),
    };

    let result = service::category::modify_by_id(state.db_pool, dto, claim.id).await;

    match result {
        Ok(model) => RespVO::<Model>::success("success".to_owned(), Some(model)).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn delete_by_id(
    _claim: Claims,
    State(state): State<AppState>,
    Query(query): Query<category::DeleteByID>,
) -> Response<Body> {
    let result = service::category::delete_by_id(state.db_pool, query.category_id).await;

    match result {
        Ok(delete_res) => {
            let rows_affected = delete_res.rows_affected;

            RespVO::<serde_json::Value>::success(
                "success".to_owned(),
                Some(json!({ "rows_affected": rows_affected })),
            )
            .into_response()
        }
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn query_by_type(
    State(state): State<AppState>,
    Query(query): Query<category::QueryByType>,
) -> Response<Body> {
    let result = service::category::list_by_type(state.db_pool, query.r#type).await;

    match result {
        Ok(model) => {
            RespVO::<Vec<Model>>::success("success".to_owned(), Some(model)).into_response()
        }
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn page_query(
    State(state): State<AppState>,
    Query(query): Query<CategoryPageQueryDTO>,
) -> Response<Body> {
    let result = service::category::page_query(state.db_pool, query).await;

    match result {
        Ok(model) => {
            RespVO::<PageResult<Model>>::success("success".to_owned(), Some(model)).into_response()
        }
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}
